package cn.qn.service.impl.article;

import cn.qn.base.BaseQuery;
import cn.qn.base.PageVO;
import cn.qn.dto.article.*;
import cn.qn.enums.AppUserTypeEnum;
import cn.qn.enums.ArticleMediaTypeEnum;
import cn.qn.enums.ArticleTypeEnum;
import cn.qn.enums.BooleanEnum;
import cn.qn.exceptions.BizException;
import cn.qn.mapper.article.ArticleMapper;
import cn.qn.moudle.article.Article;
import cn.qn.moudle.article.ArticleMedia;
import cn.qn.moudle.article.ArticlePraise;
import cn.qn.moudle.user.AppUser;
import cn.qn.repository.article.ArticleMediaRepository;
import cn.qn.repository.article.ArticlePraiseRepository;
import cn.qn.repository.article.ArticleRepository;
import cn.qn.repository.user.AppUserRepository;
import cn.qn.service.article.ArticleService;
import cn.qn.service.user.AppUserService;
import cn.qn.utils.SerialNoUtils;
import com.github.miemiedev.mybatis.paginator.domain.PageBounds;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @Auther: Bryant
 * @Date: 2018/6/11
 * @Description:
 */
@com.alibaba.dubbo.config.annotation.Service(interfaceClass = ArticleService.class)
@Service
public class ArticleServiceImpl implements ArticleService {

    @Resource
    private ArticleMapper articleMapper;

    @Autowired
    private ArticleRepository articleRepository;

    @Autowired
    private ArticleMediaRepository articleMediaRepository;

    @Autowired
    private ArticlePraiseRepository articlePraiseRepository;

    @Autowired
    private AppUserRepository appUserRepository;

    @Autowired
    private AppUserService appUserService;
    @Value("${aliyun.oss.showUrl}")
    private String showUrl;


    @Override
    public PageVO<ArticleDTO> pageQueryArticles(ArticleQueryDTO query) {
        PageBounds pb = new PageBounds(query.getPageBounds().getPage(), query.getPageBounds().getLimit());
        List<ArticleDTO> list = articleMapper.pageQueryArticles(query, pb);
        list.forEach(dto -> {
            dto.setShowCreateTime(DateFormatUtils.format(dto.getCreateTime(), "MM-dd HH:mm"));
            dto.setShowArticleType(ArticleTypeEnum.getDesc(dto.getArticleType()));
            dto.setShowMediaType(ArticleMediaTypeEnum.getDesc(dto.getMediaType()));
            dto.setShowUserType(AppUserTypeEnum.getDesc(dto.getUserType()));
        });
        Integer count = articleMapper.pageQueryArticlesCount(query);
        return PageVO.convert(pb.getPage(), pb.getLimit(), list, count);
    }

    @Override
    public ArticleDTO queryDetailByArticleId(String articleId) {
        ArticleDTO dto = new ArticleDTO();
        Article article = articleRepository.findByArticleId(articleId);
        AppUser appUser = appUserRepository.findByUserId(article.getUserId());
        BeanUtils.copyProperties(article, dto);
        dto.setShowCreateTime(DateFormatUtils.format(article.getCreateTime(), "MM-dd HH:mm"));
        dto.setShowArticleType(ArticleTypeEnum.getDesc(article.getArticleType()));
        dto.setShowMediaType(ArticleMediaTypeEnum.getDesc(article.getMediaType()));
        dto.setShowUserType(AppUserTypeEnum.getDesc(appUser.getUserType()));
        dto.setMobile(appUser.getMobile());
        dto.setUserType(appUser.getUserType());
        dto.setNickName(appUser.getNickName());
        dto.setMedias(findByArticleId(articleId));
        return dto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void publishArticle(ArticleAddDTO dto) {
        Article article = new Article();
        BeanUtils.copyProperties(dto,article);
        article.setArticleId(SerialNoUtils.createArticleId());
        article.setMediaNum(dto.getMedias()==null?0:dto.getMedias().size());
        article.setReadNum(0);
        article.setPraiseNum(0);
        article.setStatus(BooleanEnum.TRUE.getStringCode());
        article.setCreateTime(new Date());
        articleRepository.save(article);
        saveArticleMedia(article.getArticleId(),dto.getMedias());
    }

    @Override
    public void editArticleStatus(String  articleId,String userName) {
        Article article =articleRepository.findByArticleId(articleId);
        if(null==article){
            throw new BizException("文章不存在");
        }
        article.setStatus(article.getStatus().equals(BooleanEnum.TRUE.getStringCode())?BooleanEnum.FALSE.getStringCode():BooleanEnum.TRUE.getStringCode());
        article.setUpdateBy(userName);
        article.setUpdateTime(new Date());
        articleRepository.save(article);
    }

    @Override
    public void setTopStatusChange(String articleId, String userName) {
        Article article =articleRepository.findByArticleId(articleId);
        if(null==article){
            throw new BizException("文章不存在");
        }
        article.setSetTop(article.getSetTop().equals(BooleanEnum.TRUE.getStringCode())?BooleanEnum.FALSE.getStringCode():BooleanEnum.TRUE.getStringCode());
        article.setUpdateBy(userName);
        article.setUpdateTime(new Date());
        articleRepository.save(article);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteArticle(String articleId) {
        Article article =articleRepository.findByArticleId(articleId);
        if(null==article){
            throw new BizException("文章不存在");
        }
        articleRepository.delete(article);
        List<ArticleMedia> medias = articleMediaRepository.findByArticleId(articleId);
        articleMediaRepository.deleteInBatch(medias);
    }

    @Override
    public PageVO<AppArticleDTO> pageQueryAppArticles(AppArticleQueryDTO query) {
        PageBounds pb = new PageBounds(query.getPageBounds().getPage(), query.getPageBounds().getLimit());
        List<String> userIds = appUserService.queryAttionUserIds(query.getUserId());
        if(query.getAttention()==true){
            query.setUserIds(userIds);
        }
        List<AppArticleDTO> list = articleMapper.pageQueryAppArticles(query, pb);
        list.forEach(dto -> {
            dto.setShowCreateTime(DateFormatUtils.format(dto.getCreateTime(), "MM-dd HH:mm"));
            dto.setAttention(userIds!=null?userIds.contains(dto.getUserId()):false);
            dto.setMedias(findByArticleId(dto.getArticleId()));
            dto.setHeadImg(showUrl+dto.getHeadImg());
        });
        Integer count = articleMapper.pageQueryAppArticlesCount(query);
        return PageVO.convert(pb.getPage(), pb.getLimit(), list, count);
    }

    @Override
    public Integer countByUserId(String userId) {
        return articleRepository.countByUserId(userId);
    }

    @Override
    public void appPublishArticle(String userId, ArticleAddVo vo) {
        Article article = new Article();
        article.setUserId(userId);
        article.setArticleId(SerialNoUtils.createArticleId());
        article.setArticleType(ArticleTypeEnum.NORMAL.getCode());
        article.setContent(vo.getContent());
        article.setAddress(vo.getAddress());
        article.setMediaType(vo.getMediaType());
        article.setMediaNum(vo.getMedias()==null?0:vo.getMedias().size());
        article.setReadNum(0);
        article.setPraiseNum(0);
        article.setStatus(BooleanEnum.TRUE.getStringCode());
        article.setCreateTime(new Date());
        articleRepository.save(article);
        saveArticleMedia(article.getArticleId(),vo.getMedias());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void praiseArticle(String userId, String articleId) throws BizException{
        Article article = articleRepository.findByArticleId(articleId);
        if(article==null){
            throw new BizException("文章不存在");
        }
        ArticlePraise articlePraise=articlePraiseRepository.findByArticleIdAndUserId(articleId,userId);
        if(null!=articlePraise){
            throw new BizException("已点过赞");
        }
        articlePraise=new ArticlePraise();
        articlePraise.setArticleId(articleId);
        articlePraise.setUserId(userId);
        articlePraise.setCreateTime(new Date());
        articlePraiseRepository.save(articlePraise);
        article.setPraiseNum(article.getPraiseNum()+1);
        articleRepository.save(article);
    }

    private List<ArticleMediaDTO> findByArticleId(String articleId) {
        List<ArticleMediaDTO> list = new ArrayList<>();
        List<ArticleMedia> articleMedias = articleMediaRepository.findByArticleId(articleId);
        articleMedias.forEach(m -> {
            ArticleMediaDTO dto = new ArticleMediaDTO();
            dto.setMediaPath(m.getMediaPath());
            dto.setFullMediaPath(showUrl + dto.getMediaPath());
            list.add(dto);
        });
        return list;
    }

    private void saveArticleMedia(String articleId,List<String> medias) {
        List<ArticleMedia> oldMedia = articleMediaRepository.findByArticleId(articleId);
        articleMediaRepository.deleteInBatch(oldMedia);
        if(null!=medias){
            medias.forEach(m->{
                ArticleMedia media=new ArticleMedia();
                media.setArticleId(articleId);
                media.setMediaPath(m);
                articleMediaRepository.save(media);
            });
        }
    }
}
